package com.atguigu.spzx.common.log.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.log.annotation.Log;
import com.atguigu.spzx.common.log.enums.OperatorType;
import com.atguigu.spzx.common.log.service.SysOperLogService;
import com.atguigu.spzx.model.entity.system.SysOperLog;
import com.atguigu.spzx.model.entity.system.SysUser;
import com.atguigu.spzx.model.entity.system.SysUserThreadLocalAuthContextUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
public class LogAspect {

    @Autowired
    private SysOperLogService sysOperLogService;

    @SneakyThrows
    @Around("@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog){
        //新建一个日志对象,封装日志数据
        SysOperLog sysOperLog = new SysOperLog();
        beforeLog(joinPoint,sysLog,sysOperLog);  //把需要的对象传入beforeLog方法,封装日志信息.
        //执行方法
        Object proceed=null;
        try{
            proceed = joinPoint.proceed();
        }catch (Exception e){
            //发生异常的情况
            String errorMessage = e.getMessage();
            //保存异常时的数据
            afterLog(null,sysLog,sysOperLog,1,errorMessage);
            //保存日志
            sysOperLogService.saveLog(sysOperLog);
            //抛出异常,将控制权交给上级异常处理器  (此处抛出后,后续代码都不执行了.)
            throw new Exception(e);
        }
        //没有发生异常的情况
        //保存正常的数据
        afterLog(proceed,sysLog,sysOperLog,0,null);
        System.out.println(sysOperLog);
        //保存日志
        sysOperLogService.saveLog(sysOperLog);
        return proceed;
    }

    private void afterLog(Object proceed, Log sysLog, SysOperLog sysOperLog, int status, String errorMessage) {
        sysOperLog.setStatus(status);
        if(status==1){
            //此处为异常情况
            sysOperLog.setErrorMsg(errorMessage);
        }else{
            //此处为正常执行情况
            if (proceed!=null){
                sysOperLog.setJsonResult(JSON.toJSONString(proceed));
            }
        }
    }


    private void beforeLog(ProceedingJoinPoint joinPoint, Log sysLog, SysOperLog sysOperLog) {
        // 注解信息
        int i = sysLog.businessType();// 业务类型
        String title = sysLog.title();// 模块名
        OperatorType operatorType = sysLog.operatorType(); //操作人类别
        sysOperLog.setBusinessType(i);
        sysOperLog.setTitle(title);
        sysOperLog.setOperatorType(operatorType.name());

        // http信息
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String method = request.getMethod();  //获取请求方式
        String ip = request.getRemoteAddr();  //获取请求ip地址
        StringBuffer requestURL = request.getRequestURL(); //获取请求路径url
        String queryString = request.getQueryString();
        sysOperLog.setOperUrl(requestURL.toString());
        sysOperLog.setOperParam(queryString);
        sysOperLog.setRequestMethod(method);
        sysOperLog.setOperIp(ip);

        // 方法本身
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        String name = methodSignature.getName();   //获取方法名称并封装
        sysOperLog.setMethod(name);
        SysUser sysUser = SysUserThreadLocalAuthContextUtil.get();
        sysOperLog.setOperName(sysUser.getUsername());  //获取用户名并封装

    }
}
